package com.neusoft.databus.core.converter;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.collect.Maps;
import com.neusoft.bizcore.web.dto.AbstractConverter;
import com.neusoft.bizcore.web.utils.JsonUtils;
import com.neusoft.bizcore.web.utils.id.BaseIdGenerator;
import com.neusoft.databus.common.constant.DatabusConstant;
import com.neusoft.databus.common.dto.MetricDTO;
import com.neusoft.databus.common.enums.MetricValueType;
import com.neusoft.databus.common.model.Metric;
import com.neusoft.databus.common.model.MetricGroup;
import com.neusoft.databus.common.utils.StringFormatUtils;
import com.neusoft.databus.core.repository.MetricRepository;
import com.neusoft.databus.core.vo.MetricPortVO;

/**
 * Metric Model和DTO转换器
 *
 * @author sunchf
 * @date 2018年12月24日 上午9:44:01
 */
@Component
public class MetricConverter extends AbstractConverter<Metric, MetricDTO> {

    @Autowired
    private MetricRepository metricRepository;
    @Autowired
    private BaseIdGenerator metricCodeGenerator;

    private final static String HASHTAG = "#";

    @Override
    public Metric toModel(final MetricDTO dto) {
        Metric model;
        if (dto.isNew()) {
            model = new Metric();
            model.setCode(this.metricCodeGenerator.generateCode());
        } else {
            model = this.metricRepository.getOne(dto.getId());
        }
        model.setName(dto.getName());
        model.setVariable(dto.getVariable());
        model.setValueType(dto.getValueType());
        model.setRule(dto.getRule());
        model.setCommand(dto.getCommand().trim());
        model.setUnit(dto.getUnit());
        model.setValueCategory(dto.getValueCategory());
        model.setComment(dto.getComment());
        return model;
    }

    @Override
    public MetricDTO toDTO(final Metric model, final boolean forListView) {
        final MetricDTO dto = new MetricDTO();
        dto.setId(model.getId());
        dto.setName(model.getName());
        dto.setCode(model.getCode());
        dto.setVariable(model.getVariable());
        dto.setValueType(model.getValueType());
        dto.setRule(model.getRule());
        dto.setCommand(model.getCommand().trim());
        dto.setUnit(model.getUnit());
        dto.setValueCategory(model.getValueCategory());
        dto.setComment(model.getComment());
        return dto;
    }

    public Metric toModel(final MetricPortVO metricPortVO) {
        final Metric model = new Metric();
        model.setCode(this.metricCodeGenerator.generateCode());
        model.setName(metricPortVO.getName());
        model.setVariable(metricPortVO.getVariable());
        model.setValueType(MetricValueType.valueOf(metricPortVO.getValueType().toUpperCase()));
        model.setUnit(metricPortVO.getUnit());
        final Map<String, Object> ruleMap = Maps.newHashMap();
        if (StringUtils.isNotBlank(metricPortVO.getExpression())) {
            //过滤中文符号
            String expression = StringFormatUtils.cToe(metricPortVO.getExpression());
            if (expression.contains(MetricConverter.HASHTAG)) {
                if (expression.contains(DatabusConstant.METRIC_CONFIG_FLAG_EXPRSSION)) {
                    expression = expression.replace(MetricConverter.HASHTAG, metricPortVO.getVariable());
                    JsonUtils.jsonToMap(expression);
                    ruleMap.putAll(JsonUtils.jsonToMap(expression));
                } else {
                    expression = expression.replace(MetricConverter.HASHTAG, metricPortVO.getVariable());
                    ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_EXPRSSION, expression);
                }
            } else if (expression.contains(DatabusConstant.METRIC_CONFIG_FLAG_EXPRSSION)) {
                JsonUtils.jsonToMap(expression);
                ruleMap.putAll(JsonUtils.jsonToMap(expression));
            } else {
                ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_EXPRSSION, expression);
            }
        }
        if ((0 <= metricPortVO.getStart())) {
            ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_START, metricPortVO.getStart());
        }
        if ((0 <= metricPortVO.getLength())) {
            ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_LENGTH, metricPortVO.getLength());
        }
        if ((0 <= metricPortVO.getBitStart())) {
            ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_BIT_START, metricPortVO.getBitStart());
        }
        if ((0 <= metricPortVO.getBitLength())) {
            ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_BIT_LENGTH, metricPortVO.getBitLength());
        }
        if ((0 <= metricPortVO.getPrecisionBits())) {
            ruleMap.put(DatabusConstant.METRIC_CONFIG_FLAG_PRECISION, metricPortVO.getPrecisionBits());
        }
        model.setRule(JsonUtils.pojoToJson(ruleMap).toString());
        model.setCommand(metricPortVO.getCommand().trim());
        return model;
    }

    public MetricPortVO toVO(final Metric model) {
        final MetricPortVO metricPortVO = new MetricPortVO();
        metricPortVO.setName(model.getName());
        metricPortVO.setVariable(model.getVariable());
        metricPortVO.setValueType(model.getValueType().toString().toLowerCase());
        metricPortVO.setCommand(model.getCommand().trim());
        metricPortVO.setUnit(model.getUnit());
        final String rule = model.getRule();
        if (StringUtils.isNotBlank(rule)) {
            final Map<String, Object> ruleMap = JsonUtils.jsonToMap(rule);
            if (ruleMap.containsKey(DatabusConstant.METRIC_CONFIG_FLAG_START)) {
                metricPortVO
                        .setStart(Integer.valueOf(ruleMap.get(DatabusConstant.METRIC_CONFIG_FLAG_START).toString()));
                ruleMap.remove(DatabusConstant.METRIC_CONFIG_FLAG_START);
            }
            if (ruleMap.containsKey(DatabusConstant.METRIC_CONFIG_FLAG_LENGTH)) {
                metricPortVO
                        .setLength(Integer.valueOf(ruleMap.get(DatabusConstant.METRIC_CONFIG_FLAG_LENGTH).toString()));
                ruleMap.remove(DatabusConstant.METRIC_CONFIG_FLAG_LENGTH);
            }
            if (ruleMap.containsKey(DatabusConstant.METRIC_CONFIG_FLAG_BIT_START)) {
                metricPortVO.setBitStart(
                        Integer.valueOf(ruleMap.get(DatabusConstant.METRIC_CONFIG_FLAG_BIT_START).toString()));
                ruleMap.remove(DatabusConstant.METRIC_CONFIG_FLAG_BIT_START);
            }
            if (ruleMap.containsKey(DatabusConstant.METRIC_CONFIG_FLAG_BIT_LENGTH)) {
                metricPortVO.setBitLength(
                        Integer.valueOf(ruleMap.get(DatabusConstant.METRIC_CONFIG_FLAG_BIT_LENGTH).toString()));
                ruleMap.remove(DatabusConstant.METRIC_CONFIG_FLAG_BIT_LENGTH);
            }
            if (ruleMap.containsKey(DatabusConstant.METRIC_CONFIG_FLAG_PRECISION)) {
                metricPortVO.setPrecisionBits(
                        Integer.valueOf(ruleMap.get(DatabusConstant.METRIC_CONFIG_FLAG_PRECISION).toString()));
                ruleMap.remove(DatabusConstant.METRIC_CONFIG_FLAG_PRECISION);
            }
            if (!ruleMap.isEmpty()) {
                metricPortVO.setExpression(JsonUtils.pojoToJson(ruleMap));
            }
        }
        if (model.getGroups().size() > 0) {
            final MetricGroup metricGroup = model.getGroups().get(0);
            metricPortVO.setMetricGroupName(metricGroup.getName());
            metricPortVO.setProtocol(metricGroup.getProtocol().toString().toLowerCase());
            if (StringUtils.isNotBlank(metricGroup.getConfig())) {
                metricPortVO.setMetricGroupConfig(metricGroup.getConfig());
            }
        }
        return metricPortVO;
    }
}
